題目是一個看起來像是 Weather Widget 的介面,配上下雨的動畫,並且在初次 loading 時,月亮會有升起的動畫。
上面的圖是題目,而我們要做出幾乎一樣的樣子,題目中還有附上出題官方的CodePen,也有附上給我們解題用的template,當我們真的不會的時候,還是可以參考他們的寫法,所以沒有想像中困難。
我做好的此題CSS Challeage解答
那麼我們就開始吧。
這個題目要求我們製作一個天氣 Widget 的畫面
我們上次已經做完 下方天氣資訊 的部分,長這樣:
那我們今天先來做上方圖片的部分,這部分我會拆三個地方來寫。
.frame
.view
// ───新增的部分
.moon
- for i in (1..11)
div class="crater-#{i}"
// ───新增的部分
.label
...
首先,一樣先開版,把結構作出來。
這邊很簡單的,我就先增加一個 div
取名為 .moon
。
.moon
的作用是生成 11 個 crater
元素,每個元素的類名依次為 crater-1
到 crater-11
。
通過 for
迴圈來簡化生成多個 div
的過程,讓我們可以輕鬆建立重複的元素,這段就是在建立月球表面的隕石坑。
這樣的寫法方便快速添加多個具有相似樣式但需要獨立標識的元素,以便後續使用不同的 CSS 或 JavaScript 來針對不同的 crater
進行樣式或行為上的定制化操作。
由此可知,這段就是我們建立了一個名為 .moon
的 div
,而上面建立了 11 個 div
,它們是依次名為 crater-1
到 crater-11
的隕石坑。
$moonColor: #F6EDBD;
$moonWH: 67px;
.view {
...
.moon {
width: $moonWH;
height: $moonWH;
position: absolute;
background: $moonColor;
border-radius: 50%;
overflow: hidden;
top: 45px;
left: 55px;
box-shadow: 0 0 10px 0 $moonColor;
animation: animate-rise 1s ease-out;
}
}
用變數設定月亮的寬高跟顏色,顏色的部分一樣是使用第一天教的小工具來吸色。
width
和 height
設定了月球的大小,position: absolute
將其定位,並通過 top
和 left
調整它的位置。border-radius: 50%
將其變為圓形,並賦予背景色 (background: $moonColor
),再加上陰影效果 (box-shadow
),這段陰影是為了讓月亮有外面的光暈。animate-rise 1s ease-out
,讓月球產生緩慢升起的效果。接著我們來製作動畫,讓它從底下升起。
@keyframes animate-rise {
from {
transform: translate(-20px,200px);
}
to {
transform: translate(0,0px);
}
}
我們剛剛已經在 CSS 中設定動畫的名字要叫做 animate-rise
,所以我們就去設定一個 @keyframes
叫做 animate-rise
。
這邊要做的就是把它在地平線底下的位置定義出來,然後讓它藉由 from
到 to
,自然的去移動位置,最終移動到我們剛剛已經設定好的最終月亮位置。這樣月亮升起的動畫就完成了。
.view {
...
.moon {
...
// crater
.crater {
&-1 {
position: absolute;
width: 11px;
height: 11px;
top: 9px;
left: 28px;
border-radius: 10px;
background: #ECE1A8;
}
&-2 {
@extend .crater-1;
top: 12px;
left: 0;
}
...
}
}
}
我在這裡先定義了 .crater-1
的樣式。
使用 position: absolute
定位在 top
和 left
位置。其大小和圓角通過 width
、height
和 border-radius
控制,並賦予了淡黃色的背景色 (background: #ECE1A8
),模擬月球表面的坑洞效果。
@extend
用來繼承其他隕石坑的樣式,這樣可以避免重複代碼,並針對特定的隕石坑進行細微的調整,如位置 (top
, left
) 和大小 (width
, height
) 等。
這邊我是一個個微調每個坑洞的所在位置跟大小,需要花比較多時間自行調整。在調整大小的時候,可以先把動畫那行註解掉,就不會一直跑動畫。
我在這邊就只貼出部分隕石坑的代碼,要看更詳細的可以去我的 codepen 察看。
隕石坑都調整好了之後會長這樣:
從題目可以看出,背景的山坡地其實分成了前後兩個部分,兩塊的顏色也不太一樣。
所以這邊我們就分兩個部分來寫。
.frame
.view
.moon
...
// ───新增的部分
- for i in (1..2)
div class="ground-bg-#{i}"
- for i in (1..3)
div class="ground-front-#{i}"
// ───新增的部分
.label
...
這邊我們使用迴圈在 HTML 中生成 ground-bg
和 ground-front
的元素。每個元素的 class 名稱根據迴圈計數器動態生成。
for i in (1..2)
:這是生成兩個 .ground-bg
元素,class 分別是 ground-bg-1
和 ground-bg-2
。for i in (1..3)
:這是生成三個 .ground-front
元素,class 分別是 ground-front-1
、ground-front-2
和 ground-front-3
。$groundBG_Color: #26314E;
$groundFront_Color: #303C5D;
.ground {
&-bg {
&-1 {
position: absolute;
width: 337px;
height: 280px;
top: 201px;
left: -57px;
background-color: $groundBG_Color;
border-radius: 50%;
}
&-2 {
@extend .ground-bg-1;
top: 197px;
left: 177px;
}
}
&-front {
...
}
}
首先,我先使用變數定義好前後兩個山坡地的背景顏色,接著我們先來寫後面的山坡地。
山坡地的圓形其實就是一個大的圓,但我們只顯示它們的邊角一部分,其餘的部分在 .frame
的 overflow: hidden
的作用下就會隱藏掉。
我們讓,.ground
包含兩個子元素:.ground-bg
和 .ground-front
,並使用 Sass 的 @extend
功能來複製樣式:
.ground-bg
定義了兩個背景元素,分別是使用ground-bg-1
和 ground-bg-2
,我們使用 position: absolute
來控制位置和大小,並有不同的 top
和 left
屬性調整位置,background-color
。
ground-bg-2
extend 了 ground-bg-1
的樣式,所以可以減少重複的程式碼,我們只需要修改他的位置就可以了。
接著我們來寫前面的山坡地:
.ground {
&-bg {
...
}
&-front {
&-1 {
@extend .ground-bg-1;
background: $groundFront_Color;
top: 248px;
left: -136px;
}
&-2 {
@extend .ground-front-1;
top: 220px;
left: 65px;
}
...
}
}
.ground-front
則擴展了 .ground-bg
的樣式,並且改變了顏色和位置來形成前景圖層。
這邊一樣將 ground-front-2
至 ground-front-3
都去 extend .ground-front-1
的樣式,如此變可以不用重複寫背景色。再修改一下各自的位置,背景的山坡地就完成了。
由於篇幅太長了,我決定再分篇寫,下一篇再來寫後面的 下雨的動畫。
希望改變了這種按照步驟的寫法,能讓更多人看得懂,也能跟我一樣喜歡上寫CSS。
那今天就先到這裡,明天我們再繼續來玩下一集。